﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;

namespace 贪吃蛇 
{
    enum E_MoveDir    // 表示当前移动方向的枚举 
    {
        /// <summary>
        /// 上 
        /// </summary>
        Up,
        /// <summary>
        /// 下
        /// </summary>
        Down,
        /// <summary>
        /// 左
        /// </summary>
        Left,
        /// <summary>
        /// 右
        /// </summary>
        Right
    }

    //容器长度以及记录当前蛇的长度一定要弄明白  
    internal class Snake : IDraw
    {
        //同一个命名空间下 可以调用其它类
        SnakeBody[] bodys;  //蛇的身体 bodies数组名用于引用数组 
        int NowNum = 0; //记录蛇的长度,每吃一个食物长度+1
        E_MoveDir dir; //记录蛇的移动方向 
        public Snake(int x, int y)  //构造函数用于成员初始化 int x,int y传进来蛇头位置
        {
            //直接给一个200的空间 在游戏中基本不会出现蛇长度达200的情况 
            bodys = new SnakeBody[200];  //初始化长度为200的数组  

            //确定蛇的类型以及位置 调用SnakeBody的构造函数
            bodys[0] = new SnakeBody(E_SnakeBody_Type.Head, x, y);

            NowNum = 1; //初始化蛇的长度为1
            dir = E_MoveDir.Left; //初始化蛇的移动方向
        }

        public void Draw()
        {

            for (int i = 0; i < NowNum; i++)
            {
                bodys[i].Draw();  //自己画自己调用Draw函数 
            }


        }

        #region  lesson7 蛇的移动 
        public void Move()    //每次移动之后更新位置
        {  //记录最后一次蛇的位置
           //擦除最后一个蛇的位置
            SnakeBody lastsnake = bodys[NowNum - 1];
            //将光标位置放在最后一一个蛇的位置
            Console.SetCursorPosition(lastsnake.pos.x, lastsnake.pos.y);
            //执行擦除操作
            Console.WriteLine(" ");
            //在擦除后，绘制前  来画一个蛇的位置
            for(int i = NowNum - 1; i > 0; i--)  //从后往前遍历  让后一个蛇身的位置等于前一个蛇身的位置
            {
                bodys[i].pos = bodys[i - 1].pos;
            }
            switch (dir)   //判断当前移动的方向 
            {

                case E_MoveDir.Up:
                    --bodys[0].pos.y;
                    break;
                case E_MoveDir.Down:
                    ++bodys[0].pos.y;
                    break;


                case E_MoveDir.Left:
                    bodys[0].pos.x -= 2;
                    break;

                case E_MoveDir.Right:
                    bodys[0].pos.x += 2;
                    break;
                default:
                    break;
            }
        }
        #endregion
        #region Lesson8 改变蛇移动的方向 
        //写一个蛇转向的方法
        public void ChangeDir(E_MoveDir dir)
        {
            //如果//如果当前方向和要改变的方向相同则不改变
            //如果蛇向右，指定移动指定向左移动，或者蛇向上移动指定向下移动则不会执行转向的逻辑以此类推
            if (dir == this.dir || NowNum > 1 && (this.dir == E_MoveDir.Up && dir == E_MoveDir.Down || this.dir == E_MoveDir.Left && dir == E_MoveDir.Right || this.dir == E_MoveDir.Down && dir == E_MoveDir.Up || this.dir == E_MoveDir.Right && dir == E_MoveDir.Left))
            {

                return;
            }   //如果当前方向和要改变的方向相同则不改变
            this.dir = dir;   //否则的按照传入的方向进行移动 
        }
        #endregion
        #region lesson9 撞墙撞身体结束逻辑
        public bool CheckEnd(Map map)
        {
            for (int i = 0; i < map.walls.Length; i++)
            {
                if (bodys[0].pos == map.walls[i].pos)   //如果蛇头和墙相等则游戏结束
                {
                    return true;
                }
            }
            for (int i = 1; i < NowNum; i++)

            {
                if (bodys[0].pos == bodys[i].pos) //如果蛇头和身体相等则游戏结束
                    return true;
            }
            return false;


        }
        #endregion


        #region 吃食物相关 
        public bool CheckSamePos(Position p)
        {
            for(int i = 0;i<NowNum;i++) 
                {
                    if(bodys[i].pos == p)
                {
                    return true;   //如果蛇头和食物相等则返回true
                }
            }
            return false;
        }
        public void CheckEatFood(Food food)

        {
               if(bodys[0].pos == food.pos)
            {
                food.RandomPos(this); //如果蛇头和食物相等则随机生成食物    
                AddBody(); //蛇头增加一个身体   
            }
        }

        #endregion
        #region 长身体逻辑
        public void AddBody()
        {
            //先长
            SnakeBody frontBody = bodys[NowNum - 1];

            //再加长度 
            bodys[NowNum] = new SnakeBody(E_SnakeBody_Type.Head,frontBody.pos.x, frontBody.pos.y);  //暂时将创造出来的新身体和最后一节身体的位置相同

            ++NowNum;
        }

        #endregion
    }
}

